package tech.anzhen.simple.rpc.support.logging;

import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;

@Slf4j
public class LoggerInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {

        Object result = null;
        Throwable ex = null;

        try {
            result = invocation.proceed();
        } catch (Throwable e) {
            ex = e;
        }

        logDetail("invoke method => ", invocation, result, ex);

        if (ex != null) {
            throw ex;
        }
        return result;
    }

    private void logDetail(String msg, MethodInvocation invocation, Object result, Throwable ex) {

        StringBuilder sb = new StringBuilder();
        sb.append(msg);
        sb.append("method=" + methodName(invocation.getMethod()));
        sb.append(", arguments=" + formatArrays(invocation.getArguments()));
        if (result != null) {
            sb.append(", result=" + String.valueOf(result));
        }

        if (ex != null) {
            log.info(sb.toString(), ex);
        } else {
            log.info(sb.toString());
        }
    }

    private String formatArrays(Object[] array) {
        ArrayList<String> list = new ArrayList<String>();
        for (Object o : array) {
            list.add(String.valueOf(o));
        }
        return "[" + StringUtils.join(list, ",") + "]";
    }

    private String methodName(Method method) {
        String className = method.getDeclaringClass().getName();
        return className + "." + method.getName();
    }
}
